﻿using System;
using System.Collections.Generic;
using System.Text;
using OpenComposite.EII.Repository;
using System.Drawing;
using System.Reflection;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.ComponentModel;
using System.Diagnostics;

namespace OpenComposite.EII.Services
{
	internal class MainToolboxItem
	{
		private ItemType _typeDiagram = ItemType.Undefined;
		private ItemType _itemtype = ItemType.Undefined;
		private string _name = "";
		private string _tooltip = "";
		private Image _img = null;
		private string _componentClassName = null;
		private Type _componentClass = null;
		private string className = null;
		private string _category = null;
		private string _displayName = null;

		public MainToolboxItem(string componentClassName, string category)
		{
			this._componentClassName = componentClassName;
			this.Category = category;
		}
		public MainToolboxItem(ItemType type, string category)
		{
			this._itemtype = type;
			if ( type != ItemType.Separator ) {
				if ( !RepositoryService.GetToolboxInfos(_typeDiagram, _itemtype, out _img, out _name, out _tooltip) )
					throw new Exception("Undefined Toolbox Item.");
			}
			this.Category = category;
		}
		public MainToolboxItem(ItemType typeDiagram, ItemType type, string category)
		{
			this._typeDiagram = typeDiagram;
			this._itemtype = type;
			if ( _itemtype != ItemType.Separator ) {
				if ( !RepositoryService.GetToolboxInfos(_typeDiagram, _itemtype, out _img, out _name, out _tooltip) )
					throw new Exception("Undefined Toolbox Item.");
			}
			this.Category = category;
		}

		public ItemType DiagramType
		{
			get { return _typeDiagram; }
		}
		public ItemType ItemType
		{
			get { return _itemtype; }
		}

		public string Name
		{
			get
			{
				if ( _name == null ) {
					if ( this.ComponentClass != null ) {
						_name = ComponentClass.Name;
					} else
						_name = "Unknown Item";
				}
				return _name;
			}
		}
		public string DisplayName
		{
			get
			{
				if ( !string.IsNullOrEmpty(_displayName) ) return _displayName;
				Type t = this.ComponentClass;
				if ( t != null ) {
					if ( _displayName != null ) return _name;
					object[] displayName = t.GetCustomAttributes(typeof(DisplayNameAttribute), true);
					if ( displayName != null && displayName.Length > 0 ) {
						DisplayNameAttribute attr = (DisplayNameAttribute)displayName[0];
						_displayName = attr.DisplayName;
						return _displayName;
					}

					object[] toolBoxItem = t.GetCustomAttributes(typeof(ToolboxItemAttribute), true);
					if ( toolBoxItem != null && toolBoxItem.Length > 0 ) {
						Type titype = ( (ToolboxItemAttribute)toolBoxItem[0] ).ToolboxItemType;
						ConstructorInfo ci = titype.GetConstructor(new Type[] { typeof(Type) });
						string name = titype.GetProperty("DisplayName")
							.GetValue(ci.Invoke(new object[] { t }), null) as string;
						if ( !string.IsNullOrEmpty(name) ) {
							_displayName = name;
							return _displayName;
						}
					}
				}
				return this.Name;
			}
		}
		public string ToolTip
		{
			get
			{
				if ( string.IsNullOrEmpty(_tooltip) ) {
					_tooltip = this.DisplayName;
				}
				return _tooltip;
			}
		}
		public virtual Image Image
		{
			get
			{
				if ( _img == null ) {
					Type t = this.ComponentClass;

					if ( t == null ) t = typeof(Component);

					ToolboxBitmapAttribute attr = (ToolboxBitmapAttribute)TypeDescriptor
						.GetAttributes(t)[typeof(ToolboxBitmapAttribute)];

					if ( attr != null ) _img = attr.GetImage(t, false);
				}
				return _img;
			}
		}

		public Type ComponentClass
		{
			get
			{
				if ( string.IsNullOrEmpty(_componentClassName) ) return null;
				if ( _componentClass == null ) {
					_componentClass = Type.GetType(_componentClassName);
					if ( _componentClass == null ) {
						int index = _componentClassName.IndexOf(",");
						if ( index >= 0 ) _componentClassName = _componentClassName.Substring(0, index);

						foreach ( AssemblyName referencedAssemblyName in Assembly.GetExecutingAssembly().GetReferencedAssemblies() ) {
							try {
								if ( referencedAssemblyName.Name.StartsWith("Microsoft.TeamFoundation") ) {
									continue; // NEXT
								}
								Assembly assembly = Assembly.Load(referencedAssemblyName);
								if ( assembly != null ) {
									_componentClass = assembly.GetType(_componentClassName);
									if ( _componentClass != null ) break; // IF found END
								}
							} catch ( Exception ex ) {
								Debug.WriteLine(ex.ToString());
							}
						}
						if ( _componentClass == null ) {
							//Finally check in Activities and ComponentModel dll
							_componentClass = typeof(SequentialWorkflowActivity).Assembly.GetType(_componentClassName);
							if ( _componentClass == null ) {
								_componentClass = typeof(CompositeActivity).Assembly.GetType(_componentClassName);
							}
						}
					}
				}
				return _componentClass;
			}
		}
		public string ClassName
		{
			get
			{
				if ( this.ComponentClass == null ) return null;
				if ( className == null ) className = ComponentClass.FullName;
				return className;
			}
		}

		public string Category
		{
			get { return _category; }
			set { _category = value; }
		}

		public override string ToString()
		{
			if ( !string.IsNullOrEmpty(this.ClassName) ) {
				return this.ClassName;
			} else {
				return this.Name;
			}
		}

	}
}
